/*
 * @Author: liuzelin
 * @Date: 2023-01-29 10:43:35
 * @LastEditors: liuzelin
 * @LastEditTime: 2024-04-20 17:23:36
 * @Description: file content
 */
#include "panda_utils.hpp"

#include <iomanip>
#include <ctime>
#include <chrono>
#include <sstream>
#include <random>
#include <algorithm>

using namespace Panda;

static std::chrono::system_clock::time_point gSystemClockStart = std::chrono::system_clock::now();
static std::chrono::steady_clock::time_point gSteadyClockStart = std::chrono::steady_clock::now();

const char *Time::NowStr()
{
    static char buf[128] = {0};
    auto now = std::chrono::system_clock::now();
    std::time_t now_t = std::chrono::system_clock::to_time_t(now);
    auto *timeInfo = std::localtime(&now_t);
    auto mill = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
    sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
            timeInfo->tm_year + 1900,
            timeInfo->tm_mon + 1,
            timeInfo->tm_mday,
            timeInfo->tm_hour,
            timeInfo->tm_min,
            timeInfo->tm_sec,
            mill % 1000);
    return buf;
}

uint64_t Time::NowUs() {
    auto now = std::chrono::system_clock::now();
    return std::chrono::duration_cast<std::chrono::microseconds>(now - gSystemClockStart).count();
}

uint64_t Time::NowMs() { return NowUs() / 1000; }

std::string UUidGenerator::UUid()
{
    static std::random_device rd;
    static std::mt19937 e{rd()};
    static std::uniform_int_distribution<uint64_t> dist{0ULL, 0xFFFFFFFFFFFFFFFFULL};
    uint64_t ab = dist(rd);
    uint64_t cd = dist(rd);
    uint32_t a, b, c, d;
    std::stringstream ss;
    ab = (ab & 0xFFFFFFFFFFFF0FFFULL) | 0x0000000000004000ULL;
    cd = (cd & 0x3FFFFFFFFFFFFFFFULL) | 0x8000000000000000ULL;
    a = (ab >> 32U);
    b = (ab & 0xFFFFFFFFU);
    c = (cd >> 32U);
    d = (cd & 0xFFFFFFFFU);
    ss << std::hex << std::nouppercase << std::setfill('0');
    ss << std::setw(8) << (a) << '-';
    ss << std::setw(4) << (b >> 16U) << '-';
    ss << std::setw(4) << (b & 0xFFFFU) << '-';
    ss << std::setw(4) << (c >> 16U) << '-';
    ss << std::setw(4) << (c & 0xFFFFU);
    ss << std::setw(8) << d;
    return ss.str();
}

std::string UUidGenerator::ShortUUid(size_t size)
{
    std::string uuid = UUid();
    std::remove_if(uuid.begin(), uuid.end(),[](char c) {return c=='-';});
    return uuid.substr(0,size);
}
